#include "helix.h"

const char *kRadiusFlag =		"-r";
const char *kRadiusFlagLong =	"-radius";
const char *kPitchFlag =		"-p";
const char *kPitchFlagLong =	"-pitch";
const char *kEditSpans =		"-esp";
const char *kEditSpansLong =	"-editspans";
const char *kHeight =			"-he";
const char *kHeightLong =		"-height";
const char *kHelp =				"-h";
const char *kHelpLong =			"-help";

const char *helpText = 
"\n----------- \n\
use -r specify radius, \n\
use -p specify pitch, \n\
use -cvn specify cv number.\n\
-----------";

helix::helix()
{
}

helix::~helix()
{
}

MStatus helix::doIt(const MArgList& args)
{
	MStatus status;
	MArgDatabase argsdb(syntax(), args);
	
	if (argsdb.isFlagSet(kHelp))
	{
		MGlobal::displayInfo(helpText);
		return MS::kSuccess;
	}

	status = parseArgs(args);

	if (height<0.01)
	{
		MGlobal::displayError("height must greater than 0.");
		return MS::kSuccess;
	}

	if (pitch>=height)
	{
		MGlobal::displayError("pitch must less than height.");
		return MS::kSuccess;
	}
	
	if (editspans <= 3)
	{
		MGlobal::displayWarning("edit span is less than 3, use 3 as spans");
		editspans = 3;
	}

	MPointArray editpoints;
	double y_position = 0;
	for (unsigned i = 0; y_position < height; ++i)
	{
		double x = radius * cos(i);
		double y = y_position;
		double z = radius * sin(i);

		editpoints.append(MPoint(x, y, z));

		y_position += pitch;
	}

	MFnNurbsCurve curveFn;

	curveFn.createWithEditPoints(editpoints, 3, MFnNurbsCurve::kOpen, false, true, true, MObject::kNullObj, &status);
	if (!status)
	{
		MGlobal::displayError("create helix failed");
		return status;
	}
	
	return status;
}

void* helix::creator()
{
	return new helix();
}

MSyntax helix::newSyntax()
{
	MSyntax helix_syntax;

	helix_syntax.addFlag(kRadiusFlag, kRadiusFlagLong, MSyntax::kDouble);
	helix_syntax.addFlag(kPitchFlag, kPitchFlagLong, MSyntax::kDouble);
	helix_syntax.addFlag(kEditSpans, kEditSpansLong, MSyntax::kUnsigned);
	helix_syntax.addFlag(kHeight, kHeightLong, MSyntax::kDouble);
	helix_syntax.addFlag(kHelp, kHelpLong, MSyntax::kNoArg);

	return helix_syntax;
}

MStatus helix::parseArgs(const MArgList& args)
{
	MStatus status;
	MArgDatabase argdb(syntax(), args, &status);

	if (argdb.isFlagSet(kRadiusFlag))
	{
		double tmp;
		status = argdb.getFlagArgument(kRadiusFlag, 0, tmp);
		
		if (!status)
		{
			MGlobal::displayError("get radius wrong...");
			return status;
		}

		MGlobal::displayInfo(MString("get radius:") + tmp);
		radius = tmp;
	}

	if (argdb.isFlagSet(kPitchFlag, &status))
	{
		double tmp;
		status = argdb.getFlagArgument(kPitchFlag, 0, tmp);
		
		if (!status)
		{
			MGlobal::displayError("get pitch wrong...");
			return status;
		}

		MGlobal::displayInfo(MString("get pitch:") + tmp);
		pitch = tmp;
	}

	if (argdb.isFlagSet(kHeight, &status))
	{
		double tmp;
		status = argdb.getFlagArgument(kHeight, 0, tmp);

		if (!status)
		{
			MGlobal::displayError("get height wrong...");
			return status;
		}

		MGlobal::displayInfo(MString("get height:") + tmp);
		height = tmp;
	}

	if (argdb.isFlagSet(kEditSpans, &status))
	{
		unsigned tmp;
		status = argdb.getFlagArgument(kEditSpans, 0, tmp);

		if (!status)
		{
			MGlobal::displayError("get edit spans number wrong...");
			return status;
		}

		MGlobal::displayInfo(MString("get edit spans number:") + tmp);
		editspans = tmp;
	}
	    
	return MS::kSuccess;    
}
